package com.lds.register.center.client.listener;

import com.lds.management.center.common.model.dto.ResultDTO;
import com.lds.management.center.common.util.RestUtil;
import com.lds.management.center.common.util.ScheduledUtil;
import com.lds.register.center.client.common.model.request.RegisterAppInstanceRequest;
import com.lds.register.center.client.common.model.response.RegisterAppInstanceResponse;
import com.lds.register.center.client.heartbeat.service.DefaultHeartbeatService;
import com.lds.register.center.client.properties.RegisterCenterClientProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.ParameterizedTypeReference;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 应用启动时注册AppInstance
 */
@Slf4j
public class AppInstanceAutoRegistration {
    private final RegisterCenterClientProperties PROPERTIES;
    private final String URL;
    private final ParameterizedTypeReference<ResultDTO<RegisterAppInstanceResponse>> REFERENCE = new ParameterizedTypeReference<ResultDTO<RegisterAppInstanceResponse>>() {};

    public AppInstanceAutoRegistration(RegisterCenterClientProperties properties) {
        this.PROPERTIES = properties;
        this.URL = properties.getUrl() + "/api/remote/app_instance/register";
    }

    @EventListener(value = {WebServerInitializedEvent.class})
    public void autoRegister(WebServerInitializedEvent event) throws Exception {
        ScheduledUtil.defaultClosableScheduled(this::autoRegister);
    }

    private void autoRegister() {
        RegisterAppInstanceRequest request = new RegisterAppInstanceRequest();
        request.setEnvName(PROPERTIES.getEnvName());
        request.setClusterName(PROPERTIES.getClusterName());
        request.setAppName(PROPERTIES.getAppName());
        request.setAppInstanceIp(PROPERTIES.getIp());
        request.setAppInstancePort(PROPERTIES.getPort());
        request.setEphemeral(PROPERTIES.isEphemeral());
        request.setWeight(PROPERTIES.getWeight());

        if (StringUtils.isEmpty(request.getAppInstanceIp())) {
            try {
                request.setAppInstanceIp(InetAddress.getLocalHost().getHostAddress());
            } catch (UnknownHostException e) {
                // ignore
            }
        }
        ResultDTO<RegisterAppInstanceResponse> resultDTO = RestUtil.post(URL, request, REFERENCE);

        if (ResultDTO.isSuccess(resultDTO)) {
            log.info("注册AppInstance成功.");

            // 临时实例需要维持心跳
            if (PROPERTIES.isEphemeral()) {
                RegisterAppInstanceResponse appInstance = resultDTO.getData();
                new DefaultHeartbeatService(appInstance.getAppId(), appInstance.getAppInstanceId(), PROPERTIES).keepHeartbeat();
            }
        } else {
            log.error("注册AppInstance失败. cause:{}", resultDTO.getMessage());
            throw new RuntimeException(resultDTO.getMessage());
        }
    }
}
